package com.lambkit.db.sql;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lambkit.core.Lambkit;
import com.lambkit.db.meta.MetaKit;
import com.lambkit.db.meta.TableMeta;
import com.lambkit.db.mgr.MgrConstants;
import com.lambkit.db.mgr.MgrTable;
import com.lambkit.db.mgr.MgrdbService;

/**
 * @author yangyong(孤竹行)
 */
public class ExampleJsonBuilder {

    public Example build(JSONObject json, MgrTable tbc) {
        if(json==null || tbc == null) {
            return null;
        }
        Example example = Example.create(tbc.getName());

        ColumnsGroup group = new ColumnsGroup();
        if(tbc!=null) {
            group.filter(json.getJSONObject("filter"), tbc.getMeta());
        } else {
            group.filter(json.getJSONObject("filter"), null);
        }
        example.add(group);

        if(json.containsKey("group")) {
            GroupBy groupBy = new GroupBy(json.getJSONObject("group"), tbc);
            example.setGroupBy(groupBy);
        }

        generalJsonSetting(example, json);

        if(tbc!=null) {
            String columnskey = example.getLoadColumns().trim();
            if(StrUtil.isBlank(columnskey) ||  columnskey.endsWith("*")) {
                columnskey = tbc.getLoadColumns(example.getAlias());
            }
            if(StrUtil.isNotBlank(columnskey)) {
                example.setLoadColumns(columnskey);
            }
        }

        return example;
    }

    public Example build(JSONObject json, TableMeta meta) {
        if(json==null || meta == null) {
            return null;
        }
        Example example = Example.create(meta.getName());

        ColumnsGroup group = new ColumnsGroup();
        group.filter(json.getJSONObject("filter"), meta);
        example.add(group);


        if(json.containsKey("group")) {
            GroupBy groupBy = new GroupBy(json.getJSONObject("group"), meta);
            example.setGroupBy(groupBy);
        }

        generalJsonSetting(example, json);

        return example;
    }

    private void generalJsonSetting(Example example, JSONObject json) {
        String database = null;
        if (json.containsKey("database")) {
            database = json.getString("database");
        }

        if (json.containsKey("alias")) {
            example.setAlias(json.getString("alias"));
        }

        if(json.containsKey("columns")) {
            String columnskey = json.getString("columns");
            example.setLoadColumns(columnskey);
        }

        if(json.containsKey("page")) {
            example.setPage(json.getInteger("page"));
        }
        if(json.containsKey("count")) {
            example.setCount(json.getInteger("count"));
        }
        if(json.containsKey("order")) {
            example.setOrderBy(json.getString("order"));
        }
        if(json.containsKey("join")) {
            JSONArray array = json.getJSONArray("join");
            for(int i=0; i<array.size(); i++) {
                JSONObject joinObj = array.getJSONObject(i);
                JoinOn join = buildJoin(joinObj, database, example.getTableName(), example.getAlias());
                if(example.getJoinOns()==null) {
                    example.setJoinOns(CollUtil.newArrayList());
                }
                example.getJoinOns().add(join);
            }
        }
    }

    public JoinOn buildJoin(JSONObject joinObj, String database, String mainTableName, String mainAlias) {
        if (joinObj == null) {
            return null;
        }
        JoinOn join = new JoinOn();
        MgrdbService service = Lambkit.context().getBean(MgrdbService.class);
        //MgrdbService service = StrUtil.isBlank(database) ? MgrdbManager.me().getService() : MgrdbManager.me().getService(database);
        String table = joinObj.getString("table");
        if(StrUtil.isBlank(table)) {
            String tableDataAlias = joinObj.getString("data");
            if(StrUtil.isNotBlank(tableDataAlias)) {
                MgrTable tbc = service !=null ? service.createByAlias(tableDataAlias, MgrConstants.NONE, null) : null;
                if(tbc!=null) {
                    table = tbc.getName();
                }
            }
        }
        if(StrUtil.isBlank(table)) {
            return null;
        }
        join.setJoinTableName(table);

        String type = joinObj.getString("type");
        type = StrUtil.isNotBlank(type) ? type.trim().toLowerCase() : type;
        if("left".equals(type)) {
            join.setType(SqlJoinMode.LEFT_JOIN);
        } else if("right".equals(type)) {
            join.setType(SqlJoinMode.RIGHT_JOIN);
        } else if("inner".equals(type)) {
            join.setType(SqlJoinMode.INNER_JOIN);
        } else {
            join.setType(SqlJoinMode.INNER_JOIN);
        }
        String alias = joinObj.getString("alias");
        String mainTable0 = joinObj.getString("mainTable");
        mainTable0 = StrUtil.isNotBlank(mainAlias) ? mainTable0 : mainTableName;
        String mainAlias0 = joinObj.getString("mainAlias");
        mainAlias0 = StrUtil.isNotBlank(mainAlias0) ? mainAlias0 : mainAlias;

        join.setMainTableName(mainTable0);

        if(StrUtil.isNotBlank(mainAlias0)) {
            join.setMainAlias(mainAlias0);
        }
        if(StrUtil.isNotBlank(alias)) {
            join.setJoinAlias(alias);
        }

        String columnskey = null;
        if(joinObj.containsKey("columns")) {
            columnskey = joinObj.getString("columns");
        }
        if(StrUtil.isNotBlank(columnskey)) {
            join.setLoadColumns(columnskey);
        }

        JSONArray array = joinObj.getJSONArray("on");
        for(int i=0; i<array.size(); i++) {
            JSONObject onObj = array.getJSONObject(i);
            String mainField = onObj.getString("maincol");
            String joinField = onObj.getString("joincol");
            JoinOnField field = new JoinOnField(mainField, joinField);
            join.getJoinOnFields().add(field);
        }

        TableMeta joinMeta = MetaKit.createTable(database, join.getJoinTableName(), "");
        if(joinMeta!=null) {
            join.getColumnsGroup().filter(joinObj.getJSONObject("filter"), joinMeta);
        } else {
            join.getColumnsGroup().filter(joinObj.getJSONObject("filter"), null);
        }


        MgrTable joinTbc = service !=null ? service.createTable(join.getJoinTableName(), MgrConstants.NONE, null) : null;
        if(joinTbc!=null) {
            if(StrUtil.isNotBlank(columnskey)) {
                columnskey = columnskey.trim();
                if(columnskey.endsWith("*")) {
                    columnskey = joinTbc.getLoadColumns(join.getJoinAlias());
                }
            }
            if(StrUtil.isNotBlank(columnskey)) {
                join.setLoadColumns(columnskey);
            }
        }
        return join;
    }
}
